home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Programming / MiniGL / src / context.c next >
Encoding:
C/C++ Source or Header  |  2000-04-11  |  38.2 KB  |  1,369 lines

  1. /*
  2.  * $Id: context.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $
  3.  *
  4.  * $Date: 2000/04/07 19:44:51 $
  5.  * $Revision: 1.1.1.1 $
  6.  *
  7.  * (C) 1999 by Hyperion
  8.  * All rights reserved
  9.  *
  10.  * This file is part of the MiniGL library project
  11.  * See the file Licence.txt for more details
  12.  *
  13.  */
  14.  
  15. #include "sysinc.h"
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19.  
  20. static char rcsid[] = "$Id: context.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $";
  21.  
  22. extern void GLMatrixInit(GLcontext context);
  23. GLboolean MGLInitContext(GLcontext context);
  24.  
  25. #ifndef __PPC__
  26. extern struct IntuitionBase *IntuitionBase;
  27. extern struct ExecBase *SysBase;
  28. extern struct GfxBase *GfxBase;
  29. extern struct DosLibrary *DOSBase;
  30. #endif
  31.  
  32. GLcontext mini_CurrentContext;
  33. #ifdef __PPC__
  34. extern struct Library *Warp3DPPCBase;
  35. #else
  36. extern struct Library *Warp3DBase;
  37. #endif
  38. extern struct Library *CyberGfxBase;
  39.  
  40. extern void tex_FreeTextures(GLcontext context);
  41. extern void TMA_Start(LockTimeHandle *handle);
  42.  
  43. #ifndef NLOGGING
  44. int MGLDebugLevel;
  45. #endif
  46.  
  47. // Default values for new context
  48.  
  49. static int newVertexBufferSize = 40;            // Default: 40 entries in vertex buffer
  50. static int newTextureBufferSize = 2048;         // Default: 2048 texture objects
  51. static int newNumberOfBuffers = 2;              // Default: Double buffering
  52. static int newPixelDepth = 15;                  // Default: 15 bits per pixel
  53. static GLboolean newWindowMode = GL_FALSE;      // Default: Use fullscreen instead of window
  54. static GLboolean clw = GL_FALSE;                // Default: Keep workbench open
  55. static GLboolean newNoMipMapping = GL_TRUE;     // Default: No mipmapping
  56. static GLboolean newNoFallbackAlpha = GL_FALSE; // Default: Fall back to supported blend mode
  57.  
  58. static struct TagItem tags[7];
  59.  
  60. static UWORD *MousePointer = 0;
  61.  
  62. static GLboolean sys_MaybeOpenVidLibs(void)
  63. {
  64. #ifdef __PPC__
  65.     if (!Warp3DPPCBase)
  66.     {
  67.         Warp3DPPCBase = OpenLibrary("Warp3DPPC.library", 2L);
  68.         if (!Warp3DPPCBase)
  69.         {
  70.             printf("Error opening Warp3D library\n");
  71.             return GL_FALSE;
  72.         }
  73.     }
  74. #else
  75.     if (!Warp3DBase)
  76.     {
  77.         Warp3DBase = OpenLibrary("Warp3D.library", 2L);
  78.         if (!Warp3DBase)
  79.         {
  80.             printf("Error opening Warp3D library\n");
  81.             return GL_FALSE;
  82.         }
  83.     }
  84.  
  85. #endif
  86.  
  87.     if (!CyberGfxBase)
  88.     {
  89.         CyberGfxBase = OpenLibrary("cybergraphics.library", 0L);
  90.         if (!CyberGfxBase)
  91.         {
  92.             printf("Error opening cybergraphics.library\n");
  93.             return GL_FALSE;
  94.         }
  95.     }
  96.  
  97.     return GL_TRUE;
  98. }
  99.  
  100. static void vid_Pointer(struct Window *window)
  101. {
  102.     if (!MousePointer)
  103.     {
  104. #ifdef __PPC__
  105.         MousePointer = AllocVecPPC(12, MEMF_CLEAR|MEMF_CHIP,0);
  106. #else
  107.         MousePointer = AllocVec(12, MEMF_CLEAR|MEMF_CHIP);
  108. #endif
  109.     }
  110.  
  111.     if (window)         SetPointer(window, MousePointer, 1, 16, 0, 0);
  112. }
  113.  
  114. static void vid_DeletePointer(struct Window *window)
  115. {
  116.     if (window)         ClearPointer(window);
  117. #ifdef __PPC__
  118.     FreeVecPPC(MousePointer);
  119. #else
  120.     FreeVec(MousePointer);
  121. #endif
  122.     MousePointer = 0;
  123. }
  124.  
  125. void GLScissor(GLcontext context, GLint x, GLint y, GLsizei width, GLsizei height)
  126. {
  127.     //LOG(1, glScissor, "%d %d %d %d",x,y,width,height);
  128.     context->scissor.left = x;
  129.     context->scissor.top = context->w3dWindow->Height-y-height;
  130.     context->scissor.width = width;
  131.     context->scissor.height = height;
  132. }
  133.  
  134. static void vid_CloseDisplay(GLcontext context)
  135. {
  136.     int i;
  137.  
  138.     if (context->w3dContext)
  139.     {
  140.         W3D_FreeZBuffer(context->w3dContext);
  141.         tex_FreeTextures(context);
  142.         W3D_DestroyContext(context->w3dContext);
  143.         context->w3dContext = 0;
  144.     }
  145.  
  146. #ifdef __PPC__
  147.     if (Warp3DPPCBase) CloseLibrary(Warp3DPPCBase);
  148.     Warp3DPPCBase = NULL;
  149. #else
  150.     if (Warp3DBase) CloseLibrary(Warp3DBase);
  151.     Warp3DBase = NULL;
  152. #endif
  153.  
  154.     Delay(25L);
  155.     if (context->Buffers[0])
  156.     {
  157.         context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  158.         while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0]));
  159.     }
  160.  
  161.     for (i=0; i<context->NumBuffers; i++)
  162.     {
  163.         if (context->Buffers[i])
  164.             FreeScreenBuffer(context->w3dScreen, context->Buffers[i]);
  165.         context->Buffers[i] = NULL;
  166.     }
  167.  
  168.     vid_DeletePointer(context->w3dWindow);
  169.     if (context->w3dWindow) CloseWindow(context->w3dWindow);
  170.     if (context->w3dScreen) CloseScreen(context->w3dScreen);
  171.  
  172.     if (clw == GL_TRUE) OpenWorkBench();
  173. }
  174.  
  175. static GLboolean vid_ReopenDisplay(GLcontext context, int w, int h)
  176. {
  177.     ULONG ModeID, IDCMP;
  178.     int i;
  179.     struct TagItem BestModeTags[] =
  180.     {
  181.         W3D_BMI_WIDTH,  0,
  182.         W3D_BMI_HEIGHT, 0,
  183.         W3D_BMI_DEPTH,  0,
  184.         TAG_DONE,       0
  185.     };
  186.  
  187.     #ifndef NCGXDEBUG
  188.     ULONG flag;
  189.  
  190.     if (GL_FALSE == sys_MaybeOpenVidLibs())
  191.     {
  192.         return GL_FALSE;
  193.     }
  194.     #endif
  195.  
  196.     if (context->Buffers[0])
  197.     {
  198.         context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  199.         while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0]));
  200.     }
  201.  
  202.     for (i=0; i<context->NumBuffers; i++)
  203.     {
  204.         if (context->Buffers[i])
  205.             FreeScreenBuffer(context->w3dScreen, context->Buffers[i]);
  206.         context->Buffers[i] = NULL;
  207.     }
  208.  
  209.     IDCMP = context->w3dWindow->IDCMPFlags;
  210.  
  211.     if (context->w3dWindow) CloseWindow(context->w3dWindow); context->w3dWindow = NULL;
  212.     if (context->w3dScreen) CloseScreen(context->w3dScreen); context->w3dScreen = NULL;
  213.  
  214.     BestModeTags[0].ti_Data = (ULONG)w;
  215.     BestModeTags[1].ti_Data = (ULONG)h;
  216.     BestModeTags[2].ti_Data = (ULONG)newPixelDepth;
  217.  
  218.     ModeID = W3D_BestModeID(BestModeTags);
  219.  
  220.     if (ModeID == INVALID_ID) return GL_FALSE;
  221.  
  222.     context->w3dScreen = OpenScreenTags(NULL,
  223.         SA_Height,      h,
  224.         SA_Width,       w,
  225.         SA_Depth,       8L,
  226.         SA_DisplayID,   ModeID,
  227.         SA_ShowTitle,   FALSE,
  228.         SA_Draggable,   FALSE,
  229.     TAG_DONE);
  230.  
  231.     if (!context->w3dScreen)
  232.     {
  233.         printf("Failed to re-open screen\n");
  234.         return GL_FALSE;
  235.     }
  236.  
  237.     context->w3dWindow = OpenWindowTags(NULL,
  238.         WA_CustomScreen,        (ULONG)context->w3dScreen,
  239.         WA_Width,               (ULONG)context->w3dScreen->Width,
  240.         WA_Height,              (ULONG)context->w3dScreen->Height,
  241.         WA_Left,                0,
  242.         WA_Top,                 0,
  243.         WA_Title,               NULL,
  244.         WA_Flags,               WFLG_ACTIVATE|WFLG_BORDERLESS|WFLG_BACKDROP|
  245.                                 WFLG_REPORTMOUSE|WFLG_RMBTRAP,
  246.         WA_IDCMP,               IDCMP,
  247.     TAG_DONE);
  248.  
  249.     if (!context->w3dWindow)
  250.     {
  251.         printf("Failed to re-open window\n");
  252.         goto Duh;
  253.     }
  254.  
  255.     context->Buffers[0] = AllocScreenBuffer(context->w3dScreen, NULL, SB_SCREEN_BITMAP);
  256.  
  257.     if (!context->Buffers[0])
  258.     {
  259.         printf("Failed to allocate screen buffer\n");
  260.         goto Duh;
  261.     }
  262.  
  263.     #ifndef NCGXDEBUG
  264.     flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX);
  265.  
  266.     if (!flag)
  267.         printf("Warning: No CyberGraphics bitmap in buffer 0\n");
  268.     else
  269.         printf("Info: Buffer 0 is a cybergraphics bitmap\n");
  270.     #endif
  271.  
  272.  
  273.     for (i=1; i<newNumberOfBuffers; i++)
  274.     {
  275.         context->Buffers[i] = AllocScreenBuffer(context->w3dScreen, NULL, 0);
  276.         if (!context->Buffers[i]) goto Duh;
  277.  
  278.         #ifndef NCGXDEBUG
  279.         flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX);
  280.  
  281.         if (!flag)
  282.             printf("Warning: No CyberGraphics bitmap in buffer %d\n", i);
  283.         else
  284.             printf("Info: Buffer %d is a cybergraphics bitmap\n", i);
  285.         #endif
  286.     }
  287.  
  288.     context->BufNr      = 1;                    // The drawing buffer
  289.     SetRGB32(&(context->w3dScreen->ViewPort), 0, 0x7fffffff,0x7fffffff,0x7fffffff);
  290.  
  291.     for (i=0; i<context->NumBuffers; i++)
  292.     {
  293.         context->Buffers[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  294.         while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[i]));
  295.         EraseRect(context->w3dWindow->RPort, context->w3dWindow->BorderLeft,
  296.             context->w3dWindow->BorderTop,
  297.             context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight-1,
  298.             context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom-1);
  299.     }
  300.     context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  301.     while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0]));
  302.  
  303.  
  304.     GLScissor(context, 0, 0, w, h);
  305.     W3D_SetDrawRegion(context->w3dContext, context->Buffers[1]->sb_BitMap,
  306.         0, &(context->scissor));
  307.     W3D_FreeZBuffer(context->w3dContext);
  308.     W3D_AllocZBuffer(context->w3dContext);
  309.  
  310.     vid_Pointer(context->w3dWindow);
  311.                      
  312.     return GL_TRUE;
  313.  
  314. Duh:
  315.     printf("An error occured - closing down\n");
  316.     vid_CloseDisplay(context);
  317.     return GL_FALSE;
  318. }
  319.  
  320. static GLboolean vid_OpenDisplay(GLcontext context, int pw, int ph, ULONG id)
  321. {
  322.     ULONG ModeID;
  323.     ULONG CError;
  324.     int i;
  325.     ULONG result;
  326.     #ifndef NCGXDEBUG
  327.     ULONG flag;
  328.     #endif
  329.     int w, h;
  330.  
  331.     struct TagItem BestModeTags[] =
  332.     {
  333.         W3D_BMI_WIDTH,  0,
  334.         W3D_BMI_HEIGHT, 0,
  335.         W3D_BMI_DEPTH,  0,
  336.         TAG_DONE,       0
  337.     };
  338.  
  339.     if (GL_FALSE == sys_MaybeOpenVidLibs())
  340.     {
  341.         return GL_FALSE;
  342.     }
  343.  
  344.     if (id != MGL_SM_BESTMODE && id != MGL_SM_WINDOWMODE)
  345.     {
  346.         ModeID = id;
  347.     }
  348.     else
  349.     {
  350.         w = pw;
  351.         h = ph;
  352.         BestModeTags[0].ti_Data = (ULONG)w;
  353.         BestModeTags[1].ti_Data = (ULONG)h;
  354.         BestModeTags[2].ti_Data = (ULONG)newPixelDepth;
  355.  
  356.         ModeID = W3D_BestModeID(BestModeTags);
  357.     }
  358.  
  359.     if (clw == GL_TRUE) CloseWorkBench();
  360.  
  361.     if (ModeID == INVALID_ID) return GL_FALSE;
  362.  
  363.     context->w3dScreen = OpenScreenTags(NULL,
  364.             SA_Depth,       8L,
  365.             SA_DisplayID,   ModeID,
  366.             SA_ShowTitle,   FALSE,
  367.             SA_Draggable,   FALSE,
  368.         TAG_DONE);
  369.  
  370.     if (context->w3dScreen && id != MGL_SM_BESTMODE)
  371.     {
  372.         w = context->w3dScreen->Width;
  373.         h = context->w3dScreen->Height;
  374.     }
  375.  
  376.     if (!context->w3dScreen) return GL_FALSE;
  377.  
  378.     // We don't include IDCMP flags. The user can change this with
  379.     // a call to ModifyIDCMP.
  380.  
  381.     context->w3dWindow = OpenWindowTags(NULL,
  382.         WA_CustomScreen,        (ULONG)context->w3dScreen,
  383.         WA_Width,               (ULONG)context->w3dScreen->Width,
  384.         WA_Height,              (ULONG)context->w3dScreen->Height,
  385.         WA_Left,                0,
  386.         WA_Top,                 0,
  387.         WA_Title,               NULL,
  388.         WA_Flags,               WFLG_ACTIVATE|WFLG_BORDERLESS|WFLG_BACKDROP|
  389.                                 WFLG_REPORTMOUSE|WFLG_RMBTRAP,
  390.     TAG_DONE);
  391.  
  392.     if (!context->w3dWindow) goto Duh;
  393.  
  394.     context->Buffers[0] = AllocScreenBuffer(context->w3dScreen, NULL, SB_SCREEN_BITMAP);
  395.     if (!context->Buffers[0])
  396.     {
  397.         printf("Error: Can't create screen buffer 0\n");
  398.         goto Duh;
  399.     }
  400.  
  401.     #ifndef NCGXDEBUG
  402.     flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX);
  403.  
  404.     if (!flag)
  405.         printf("Warning: No CyberGraphics bitmap in buffer 0\n");
  406.     else
  407.         printf("Info: Buffer 0 is a cybergraphics bitmap\n");
  408.     #endif
  409.  
  410.  
  411.     for (i=1; i<newNumberOfBuffers; i++)
  412.     {
  413.         context->Buffers[i] = AllocScreenBuffer(context->w3dScreen, NULL, 0);
  414.         if (!context->Buffers[i])
  415.         {
  416.             printf("Error: Can't create screen buffer %d\n", i);
  417.             goto Duh;
  418.         }
  419.         #ifndef NCGXDEBUG
  420.         flag = GetCyberMapAttr(context->Buffers[0]->sb_BitMap, CYBRMATTR_ISCYBERGFX);
  421.  
  422.         if (!flag)
  423.             printf("Warning: No CyberGraphics bitmap in buffer %d\n", i);
  424.         else
  425.             printf("Info: Buffer 0 is a cybergraphics bitmap\n");
  426.         #endif
  427.     }
  428.  
  429.     context->BufNr      = 1;                    // The drawing buffer
  430.     context->NumBuffers = newNumberOfBuffers;   // So we know the limit
  431.     context->DoSync     = GL_TRUE;              // Enable sync'ing
  432.  
  433.     tags[0].ti_Tag      = W3D_CC_MODEID;
  434.     tags[0].ti_Data     = ModeID;
  435.  
  436.     tags[1].ti_Tag      = W3D_CC_BITMAP;
  437.     tags[1].ti_Data     = (ULONG)(context->Buffers[1]->sb_BitMap);
  438.  
  439.     tags[2].ti_Tag      = W3D_CC_DRIVERTYPE;
  440.     tags[2].ti_Data     = W3D_DRIVER_BEST;
  441.  
  442.     tags[3].ti_Tag      = W3D_CC_FAST;
  443.     tags[3].ti_Data     = FALSE;
  444.  
  445.     tags[4].ti_Tag      = W3D_CC_YOFFSET;
  446.     tags[4].ti_Data     = 0;
  447.  
  448.     tags[5].ti_Tag      = W3D_CC_GLOBALTEXENV;
  449.     tags[5].ti_Data     = TRUE;
  450.  
  451.     tags[6].ti_Tag      = TAG_DONE;
  452.  
  453.     context->w3dContext = W3D_CreateContext(&CError, tags);
  454.  
  455.     if (!context->w3dContext || CError != W3D_SUCCESS)
  456.     {
  457.         switch(CError)
  458.         {
  459.             case W3D_ILLEGALINPUT:
  460.                     printf("Illegal input to CreateContext function\n");
  461.                     break;
  462.             case W3D_NOMEMORY:
  463.                     printf("Out of memory\n");
  464.                     break;
  465.             case W3D_NODRIVER:
  466.                     printf("No suitable driver found\n");
  467.                     break;
  468.             case W3D_UNSUPPORTEDFMT:
  469.                     printf("Supplied bitmap cannot be handled by Warp3D\n");
  470.                     break;
  471.             case W3D_ILLEGALBITMAP:
  472.                     printf("Supplied bitmap not properly initialized\n");
  473.                     break;
  474.             default:
  475.                     printf("An error has occured... gosh\n");
  476.         }
  477.         goto Duh;
  478.     }
  479.     /*
  480.     ** Set up a few initial states
  481.     ** We always enable scissoring and dithering, since it looks better
  482.     ** on 16 bit displays.
  483.     ** We also set shading to smooth (Gouraud).
  484.     */
  485.     W3D_SetState(context->w3dContext, W3D_DITHERING,    W3D_ENABLE);
  486.     W3D_SetState(context->w3dContext, W3D_SCISSOR,      W3D_ENABLE);
  487.     W3D_SetState(context->w3dContext, W3D_GOURAUD,      W3D_ENABLE);
  488.     W3D_SetState(context->w3dContext, W3D_PERSPECTIVE,  W3D_ENABLE);
  489.     SetRGB32(&(context->w3dScreen->ViewPort), 0, 0x7fffffff,0x7fffffff,0x7fffffff);
  490.  
  491.     /*
  492.     ** Allocate the ZBuffer.
  493.     */
  494.     result = W3D_AllocZBuffer(context->w3dContext);
  495.  
  496.     switch(result)
  497.     {
  498.         case W3D_NOGFXMEM:      printf("No ZBuffer: Memory shortage\n");            break;
  499.         case W3D_NOZBUFFER:     printf("No ZBuffer: Operation not supported\n");    break;
  500.         case W3D_NOTVISIBLE:    printf("No ZBuffer: Screen is not visible\n");      break;
  501.     }
  502.  
  503.     W3D_SetState(context->w3dContext, W3D_ZBUFFER, W3D_DISABLE);
  504.     W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE);
  505.     W3D_SetZCompareMode(context->w3dContext, W3D_Z_LESS);
  506.  
  507.     for (i=0; i<context->NumBuffers; i++)
  508.     {
  509.         context->Buffers[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  510.         while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[i]));
  511.         EraseRect(context->w3dWindow->RPort, context->w3dWindow->BorderLeft,
  512.             context->w3dWindow->BorderTop,
  513.             context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight-1,
  514.             context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom-1);
  515.     }
  516.  
  517.     context->Buffers[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  518.     while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[0]));
  519.  
  520.  
  521.     GLScissor(context, 0,0, w,h);
  522.  
  523.     context->w3dLocked = GL_FALSE;
  524.  
  525.     /*
  526.     ** Select a texture format that needs no conversion
  527.     */
  528.     //FIXME:Really do it. This is lame
  529.     context->w3dFormat = W3D_A1R5G5B5;
  530.     context->w3dAlphaFormat = W3D_A4R4G4B4;
  531.     context->w3dBytesPerTexel = 2;
  532.  
  533.     vid_Pointer(context->w3dWindow); 
  534.                      
  535.     return GL_TRUE;
  536.  
  537. Duh:
  538.     for (i=0; i<newNumberOfBuffers; i++)
  539.     {
  540.         if (context->Buffers[i])
  541.         {
  542.             FreeScreenBuffer(context->w3dScreen, context->Buffers[i]);
  543.             context->Buffers[i] = NULL;
  544.         }
  545.     }
  546.  
  547.     if (context->w3dWindow)
  548.     {
  549.         CloseWindow(context->w3dWindow);
  550.         context->w3dWindow = NULL;
  551.     }
  552.  
  553.     if (context->w3dScreen)
  554.     {
  555.         CloseScreen(context->w3dScreen);
  556.         context->w3dScreen = NULL;
  557.     }
  558.  
  559.     return GL_FALSE;
  560. }
  561.  
  562. static void vid_CloseWindow(GLcontext context)
  563. {
  564.     if (context->w3dContext)
  565.     {
  566.         W3D_FreeZBuffer(context->w3dContext);
  567.         tex_FreeTextures(context);
  568.         W3D_DestroyContext(context->w3dContext);
  569.         context->w3dContext = 0;
  570.     }
  571.  
  572. #ifdef __PPC__
  573.     if (Warp3DPPCBase)          CloseLibrary(Warp3DPPCBase);
  574.     Warp3DPPCBase = NULL;
  575. #else
  576.     if (Warp3DBase)             CloseLibrary(Warp3DBase);
  577.     Warp3DBase = NULL;
  578. #endif
  579.  
  580.     if (context->w3dWindow)     CloseWindow(context->w3dWindow);
  581.     if (context->w3dScreen)     CloseScreen(context->w3dScreen);
  582.     if (context->w3dBitMap)     FreeBitMap(context->w3dBitMap);
  583.     if (context->w3dRastPort)   free(context->w3dRastPort);
  584. }
  585.  
  586.  
  587. static GLboolean vid_OpenWindow(GLcontext context, int w, int h)
  588. {
  589.     ULONG CError;
  590.     ULONG result;
  591.  
  592.     if (GL_FALSE == sys_MaybeOpenVidLibs())
  593.     {
  594.         return GL_FALSE;
  595.     }
  596.  
  597.     context->w3dScreen = LockPubScreen(NULL);
  598.     if (!context->w3dScreen) return GL_FALSE;
  599.  
  600.     // We don't include IDCMP flags. The user can change this with
  601.     // a call to ModifyIDCMP.
  602.  
  603.     context->w3dWindow = OpenWindowTags(NULL,
  604.         WA_PubScreen,           (ULONG)context->w3dScreen,
  605.         WA_InnerWidth,          (ULONG)w,
  606.         WA_InnerHeight,         (ULONG)h,
  607.         WA_Left,                30,
  608.         WA_Top,                 30,
  609.         WA_Title,               (ULONG)"MiniGL Display",
  610.         WA_DragBar,             TRUE,
  611.         WA_DepthGadget,         TRUE,
  612.         WA_Flags,               WFLG_ACTIVATE|WFLG_REPORTMOUSE|WFLG_RMBTRAP,
  613.     TAG_DONE);
  614.  
  615.     if (!context->w3dWindow) goto Duh;
  616.  
  617.     context->BufNr      = 0;                    // The drawing buffer
  618.     context->NumBuffers = 0;                    // Indicates we're using a window
  619.     context->DoSync     = GL_TRUE;              // Enable sync'ing
  620.  
  621.     context->w3dBitMap  = AllocBitMap(w,h,8,BMF_MINPLANES|BMF_DISPLAYABLE,
  622.         context->w3dWindow->RPort->BitMap);
  623.     if (!context->w3dBitMap) goto Duh;
  624.  
  625.     context->w3dRastPort = malloc(sizeof(struct RastPort));
  626.     if (!context->w3dRastPort)
  627.     {
  628.         printf("Error: unable to allocate rastport memory\n");
  629.         goto Duh;
  630.     }
  631.  
  632.     InitRastPort(context->w3dRastPort);
  633.     context->w3dRastPort->BitMap = context->w3dBitMap;
  634.  
  635.     tags[0].ti_Tag  = W3D_CC_BITMAP;
  636.     tags[0].ti_Data = (ULONG)(context->w3dBitMap);
  637.  
  638.     tags[1].ti_Tag  = W3D_CC_DRIVERTYPE;
  639.     tags[1].ti_Data = W3D_DRIVER_BEST;
  640.  
  641.     tags[2].ti_Tag  = W3D_CC_FAST;
  642.     tags[2].ti_Data = FALSE;
  643.  
  644.     tags[3].ti_Tag  = W3D_CC_YOFFSET;
  645.     tags[3].ti_Data = 0;
  646.  
  647.     tags[4].ti_Tag  = W3D_CC_GLOBALTEXENV;
  648.     tags[4].ti_Data = TRUE;
  649.  
  650.     tags[5].ti_Tag  = TAG_DONE;
  651.  
  652.     context->w3dContext = W3D_CreateContext(&CError, tags);
  653.     if (!context->w3dContext || CError != W3D_SUCCESS)
  654.     {
  655.         switch(CError)
  656.         {
  657.             case W3D_ILLEGALINPUT:
  658.                     printf("Illegal input to CreateContext function\n");
  659.                     break;
  660.             case W3D_NOMEMORY:
  661.                     printf("Out of memory\n");
  662.                     break;
  663.             case W3D_NODRIVER:
  664.                     printf("No suitable driver found\n");
  665.                     break;
  666.             case W3D_UNSUPPORTEDFMT:
  667.                     printf("Supplied bitmap cannot be handled by Warp3D\n");
  668.                     break;
  669.             case W3D_ILLEGALBITMAP:
  670.                     printf("Supplied bitmap not properly initialized\n");
  671.                     break;
  672.             default:
  673.                     printf("An error has occured... gosh\n");
  674.         }
  675.         goto Duh;
  676.     }
  677.     /*
  678.     ** Set up a few initial states
  679.     ** We always enable scissoring and dithering, since it looks better
  680.     ** on 16 bit displays.
  681.     ** We also set shading to smooth (Gouraud).
  682.     */
  683.     W3D_SetState(context->w3dContext, W3D_DITHERING,    W3D_ENABLE);
  684.     W3D_SetState(context->w3dContext, W3D_SCISSOR,      W3D_ENABLE);
  685.     W3D_SetState(context->w3dContext, W3D_GOURAUD,      W3D_ENABLE);
  686.     W3D_SetState(context->w3dContext, W3D_PERSPECTIVE,  W3D_ENABLE);
  687.  
  688.  
  689.     /*
  690.     ** Allocate the ZBuffer.
  691.     */
  692.     result = W3D_AllocZBuffer(context->w3dContext);
  693.     switch(result)
  694.     {
  695.         case W3D_NOGFXMEM:      printf("No ZBuffer: Memory shortage\n"); break;
  696.         case W3D_NOZBUFFER:     printf("No ZBuffer: Operation not supported\n"); break;
  697.         case W3D_NOTVISIBLE:    printf("No ZBuffer: Screen is not visible\n"); break;
  698.     }
  699.  
  700.     W3D_SetState(context->w3dContext, W3D_ZBUFFER, W3D_DISABLE);
  701.     W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE);
  702.     W3D_SetZCompareMode(context->w3dContext, W3D_Z_LESS);
  703.  
  704.     EraseRect(context->w3dWindow->RPort, context->w3dWindow->BorderLeft,
  705.         context->w3dWindow->BorderTop,
  706.         context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight-1,
  707.         context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom-1);
  708.  
  709.     GLScissor(context, 0,0, w,h);
  710.  
  711.     context->w3dLocked = GL_FALSE;
  712.  
  713.     /*
  714.     ** Select a texture format that needs no conversion
  715.     */
  716.     //FIXME:Really do it. This is lame
  717.     context->w3dFormat = W3D_A1R5G5B5;
  718.     context->w3dAlphaFormat = W3D_A4R4G4B4;
  719.     context->w3dBytesPerTexel = 2;
  720.  
  721.     return GL_TRUE;
  722.  
  723. Duh:
  724.     if (context->w3dWindow)
  725.     {
  726.         CloseWindow(context->w3dWindow);
  727.         context->w3dWindow = NULL;
  728.     }
  729.  
  730.     if (context->w3dScreen)
  731.     {
  732.         UnlockPubScreen(NULL, context->w3dScreen);
  733.         context->w3dScreen = NULL;
  734.     }
  735.  
  736.     if (context->w3dBitMap)
  737.     {
  738.         FreeBitMap(context->w3dBitMap);
  739.     }
  740.  
  741.     if (context->w3dRastPort)
  742.     {
  743.         free(context->w3dRastPort);
  744.     }
  745.  
  746.     return GL_FALSE;
  747. }
  748.  
  749.  
  750. void MGLResizeContext(GLcontext context, GLsizei width, GLsizei height)
  751. {
  752.     if (!context->w3dBitMap)
  753.     {
  754.         vid_ReopenDisplay(context, (int)width, (int)height);
  755.         context->w3dChipID = context->w3dContext->CurrentChip;
  756.     }
  757. }
  758.  
  759. void *MGLGetWindowHandle(GLcontext context)
  760. {
  761.     return context->w3dWindow;
  762. }
  763.  
  764. void mglChooseVertexBufferSize(int size)
  765. {
  766.     newVertexBufferSize = size;
  767. }
  768.  
  769. void mglChooseTextureBufferSize(int size)
  770. {
  771.     newTextureBufferSize = size;
  772. }
  773.  
  774. void mglChooseNumberOfBuffers(int number)
  775. {
  776.     newNumberOfBuffers = number;
  777. }
  778.  
  779. void mglChoosePixelDepth(int depth)
  780. {
  781.     newPixelDepth = depth;
  782. }
  783.  
  784. void mglProposeCloseDesktop(GLboolean closeme)
  785. {
  786.     clw = closeme;
  787. }
  788.  
  789. void mglProhibitMipMapping(GLboolean flag)
  790. {
  791.     newNoMipMapping = flag;
  792. }
  793.  
  794. void mglProhibitAlphaFallback(GLboolean flag)
  795. {
  796.     newNoFallbackAlpha = flag;
  797. }
  798.  
  799. void mglChooseWindowMode(GLboolean flag)
  800. {
  801.     newWindowMode = flag;
  802. }
  803.  
  804. void GLClearColor(GLcontext context, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  805. {
  806.     //LOG(2, glClearColor, "%f %f %f %f", red,green,blue,alpha);
  807.  
  808.     red *= 255.0;
  809.     green *= 255.0;
  810.     blue *= 255.0;
  811.     alpha *= 255.0;
  812.  
  813.     context->ClearColor = ((GLubyte)(alpha)<<24)
  814.                         + ((GLubyte)(red)<<16)
  815.                         + ((GLubyte)(green)<<8)
  816.                         + ((GLubyte)(blue));
  817. }
  818.  
  819. void GLDepthMask(GLcontext context, GLboolean flag)
  820. {
  821.     //LOG(2, glDepthMask, "%d", flag);
  822.     if (flag == GL_FALSE)
  823.         W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_DISABLE);
  824.     else
  825.         W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE);
  826.     context->DepthMask = flag;
  827. }
  828.  
  829. void GLDepthFunc(GLcontext context, GLenum func)
  830. {
  831.     ULONG wFunc = W3D_Z_LESS;
  832.     //LOG(2, glDepthFunc, "%d", func);
  833.     switch(func)
  834.     {
  835.         case GL_NEVER:      wFunc = W3D_Z_NEVER; break;
  836.         case GL_LESS:       wFunc = W3D_Z_LESS; break;
  837.         case GL_EQUAL:      wFunc = W3D_Z_EQUAL; break;
  838.         case GL_LEQUAL:     wFunc = W3D_Z_LEQUAL; break;
  839.         case GL_GREATER:    wFunc = W3D_Z_GREATER; break;
  840.         case GL_NOTEQUAL:   wFunc = W3D_Z_NOTEQUAL; break;
  841.         case GL_GEQUAL:     wFunc = W3D_Z_GEQUAL; break;
  842.         case GL_ALWAYS:     wFunc = W3D_Z_ALWAYS; break;
  843.         default:
  844.             GLFlagError(context, 1, GL_INVALID_ENUM);
  845.             break;
  846.     }
  847.     W3D_SetZCompareMode(context->w3dContext, wFunc);
  848. }
  849.  
  850.  
  851. void GLClearDepth(GLcontext context, GLclampd depth)
  852. {
  853.     //LOG(2, glClearDepth, "%f", depth);
  854.     context->ClearDepth = (W3D_Double)depth;
  855. }
  856.  
  857. void GLClear(GLcontext context, GLbitfield mask)
  858. {
  859.     //LOG(1, glClear, "%d", mask);
  860.     if (context->w3dLocked == GL_FALSE)
  861.         W3D_LockHardware(context->w3dContext);
  862.  
  863.     if (mask & GL_COLOR_BUFFER_BIT)
  864.     {
  865.         W3D_ClearDrawRegion(context->w3dContext, context->ClearColor);
  866.     }
  867.  
  868.  
  869.     if (mask & GL_DEPTH_BUFFER_BIT)
  870.     {
  871.         W3D_ClearZBuffer(context->w3dContext, &(context->ClearDepth));
  872.     }
  873.  
  874.  
  875.     if (context->w3dLocked == GL_FALSE)
  876.         W3D_UnLockHardware(context->w3dContext);
  877. }
  878.  
  879. #ifdef AUTOMATIC_LOCKING_ENABLE
  880. void MGLLockMode(GLcontext context, GLenum lockMode)
  881. {
  882.     context->LockMode = lockMode;
  883. }
  884. #endif
  885.  
  886. GLboolean MGLLockBack(GLcontext context, MGLLockInfo *info)
  887. {
  888.     ULONG error;
  889.     
  890.     if (context->w3dLocked == GL_TRUE)
  891.     {
  892.         error = W3D_SUCCESS;
  893.     }
  894.     else
  895.     {
  896.         error = W3D_LockHardware(context->w3dContext);
  897.     }
  898.  
  899.     if (error != W3D_SUCCESS)
  900.     {
  901.         return GL_FALSE;
  902.     }
  903.     else
  904.     {
  905.         context->w3dLocked = GL_TRUE;
  906.         TMA_Start(&(context->LockTime));
  907.         if (info)
  908.         {
  909.             info->width = context->w3dContext->width;
  910.             info->height = context->w3dContext->height;
  911.             info->depth = context->w3dContext->depth;
  912.             info->pixel_format = context->w3dContext->format;
  913.             info->base_address = context->w3dContext->drawmem;
  914.             info->pitch = context->w3dContext->bprow;
  915.         }
  916.     }
  917.     return GL_TRUE;
  918. }
  919.  
  920. GLboolean MGLLockDisplay(GLcontext context)
  921. {
  922.     ULONG error;
  923.     //LOG(1, mglLockDisplay, "");
  924. #ifndef AUTOMATIC_LOCKING_ENABLE
  925.     if (context->w3dLocked == GL_TRUE) return GL_TRUE;
  926.  
  927.     error = W3D_LockHardware(context->w3dContext);
  928.  
  929.     if (error == W3D_SUCCESS)
  930.     {
  931.         context->w3dLocked = GL_TRUE;
  932.         return GL_TRUE;
  933.     }
  934.     else
  935.     {
  936.         switch(error)
  937.         {
  938.             case W3D_NOTVISIBLE: printf("[MGLLockDisplay] Bitmap not visible\n"); break;
  939.             default: printf("[MGLLockDisplay] Error %d while locking\n", error); break;
  940.         }
  941.         return GL_FALSE;
  942.     }
  943. #else
  944.     if (context->w3dLocked == GL_TRUE) return GL_TRUE; // nothing to do if we are already locked
  945.  
  946.     switch(context->LockMode)
  947.     {
  948.         case MGL_LOCK_MANUAL:
  949.             error = W3D_LockHardware(context->w3dContext);
  950.             if (error == W3D_SUCCESS)
  951.             {
  952.                 context->w3dLocked = GL_TRUE;
  953.                 return GL_TRUE;
  954.             }
  955.             break;
  956.         case MGL_LOCK_AUTOMATIC: // These modes do not require the lock right here.
  957.         case MGL_LOCK_SMART:
  958.             return GL_TRUE;
  959.             break;
  960.     }
  961.     printf("[MGLLockDisplay] Unable to lock\n");
  962.     return GL_FALSE;            // If we got here, there was an error
  963. #endif
  964. }
  965.  
  966. void MGLUnlockDisplay(GLcontext context)
  967. {
  968.     //LOG(1, mglUnlockDisplay, "");
  969. #ifndef AUTOMATIC_LOCKING_ENABLE
  970.     if (context->w3dLocked == GL_FALSE) return;
  971.     W3D_UnLockHardware(context->w3dContext);
  972.     context->w3dLocked = GL_FALSE;
  973. #else
  974.     if (context->w3dLocked == GL_FALSE) return;
  975.     switch(context->LockMode)
  976.     {
  977.         case MGL_LOCK_AUTOMATIC:
  978.             break;
  979.         case MGL_LOCK_SMART:
  980.         case MGL_LOCK_MANUAL:
  981.             W3D_UnLockHardware(context->w3dContext);
  982.             break;
  983.     }
  984.     context->w3dLocked = GL_FALSE;
  985. #endif
  986. }
  987.  
  988. void MGLEnableSync(GLcontext context, GLboolean enable)
  989. {
  990.     context->DoSync = enable;
  991. }
  992.  
  993. void MGLSwitchDisplay(GLcontext context)
  994. {
  995.     int nowbuf = context->BufNr;
  996.     MGLUnlockDisplay(context);
  997.     
  998.     if (!context->w3dBitMap) // Fullscreen mode
  999.     {
  1000.         context->BufNr++;
  1001.         if (context->BufNr == context->NumBuffers)
  1002.             context->BufNr = 0;
  1003.  
  1004.         /*
  1005.         ** At this place, nowbuf contains the buffer we where drawing to.
  1006.         ** BufNr is the next drawing buffer.
  1007.         ** We switch nowbof to the be the display buffer, and set
  1008.         ** the draw region to the new BufNr
  1009.         */
  1010.  
  1011.         // FIXME: This may cause a context switch orgy, maybe make it 68k
  1012.         // Make nowbuf current display
  1013.         context->Buffers[nowbuf]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort = NULL;
  1014.         while (!ChangeScreenBuffer(context->w3dScreen, context->Buffers[nowbuf]));
  1015.  
  1016.         // Make BufNr the new draw area
  1017.         W3D_SetDrawRegion(context->w3dContext, context->Buffers[context->BufNr]->sb_BitMap,
  1018.             0, &(context->scissor));
  1019.  
  1020.         if (context->DoSync)
  1021.         {
  1022.             struct ViewPort *vp = &(context->w3dScreen->ViewPort);
  1023.             WaitBOVP(vp);
  1024.         }
  1025.     }
  1026.     else
  1027.     {   // Windowed mode
  1028.         ClipBlit(context->w3dRastPort,0,0,
  1029.             context->w3dWindow->RPort, context->w3dWindow->BorderLeft,
  1030.             context->w3dWindow->BorderTop,
  1031.             context->w3dWindow->Width-context->w3dWindow->BorderLeft-context->w3dWindow->BorderRight,
  1032.             context->w3dWindow->Height-context->w3dWindow->BorderTop-context->w3dWindow->BorderBottom,
  1033.             0xC0);
  1034.     }
  1035. }
  1036.  
  1037. GLboolean MGLInitContext(GLcontext context)
  1038. {
  1039.     int i;
  1040.  
  1041.     context->CurrentPrimitive   = GL_BASE;
  1042.     context->CurrentError       = GL_NO_ERROR;
  1043.  
  1044.     context->VertexBuffer       = malloc(sizeof(MGLVertex)*newVertexBufferSize);
  1045.     if (!context->VertexBuffer)
  1046.         return GL_FALSE;
  1047.  
  1048.     context->VertexBufferSize   = (GLuint)newVertexBufferSize;
  1049.     context->VertexBufferPointer= 0;
  1050.  
  1051.     context->TexBufferSize      = newTextureBufferSize;
  1052.     context->w3dTexBuffer       = malloc(sizeof(W3D_Texture *) * newTextureBufferSize);
  1053.     if (!context->w3dTexBuffer)
  1054.         return GL_FALSE;
  1055.  
  1056.     context->w3dTexMemory       = malloc(sizeof(GLubyte *) * newTextureBufferSize);
  1057.     if (!context->w3dTexMemory)
  1058.         return GL_FALSE;
  1059.  
  1060.     context->CurrentBinding     = 0;    // Indicate unbound texture object
  1061.  
  1062.     for (i=0; i<newTextureBufferSize; i++)
  1063.     {
  1064.         context->w3dTexBuffer[i] = NULL;
  1065.         context->w3dTexMemory[i] = NULL;
  1066.     }
  1067.  
  1068.     context->CurrentTexS = context->CurrentTexT = 0.0;
  1069.  
  1070.     context->PackAlign = context->UnpackAlign = 4;
  1071.  
  1072.     context->AlphaTest_State    = GL_FALSE;
  1073.     context->Blend_State        = GL_FALSE;
  1074.     context->Texture2D_State    = GL_FALSE;
  1075.     context->TextureGenS_State  = GL_FALSE;
  1076.     context->TextureGenT_State  = GL_FALSE;
  1077.     context->Fog_State          = GL_FALSE;
  1078.     context->Scissor_State      = GL_FALSE;
  1079.     context->CullFace_State     = GL_FALSE;
  1080.     context->DepthTest_State    = GL_FALSE;
  1081.     context->PointSmooth_State  = GL_FALSE;
  1082.     context->Dither_State       = GL_TRUE;
  1083.     context->ZOffset_State      = GL_FALSE;
  1084.  
  1085.     context->FogDirty           = GL_FALSE;
  1086.     context->FogStart           = 1.0;
  1087.     context->FogEnd             = 0.0;
  1088.  
  1089.     context->TexEnv    = GL_MODULATE;
  1090.     context->MinFilter = GL_NEAREST;
  1091.     context->MagFilter = GL_NEAREST;
  1092.     context->WrapS     = GL_REPEAT;
  1093.     context->WrapT     = GL_REPEAT;
  1094.  
  1095.     context->w3dFog.fog_start   = 1.0;
  1096.     context->w3dFog.fog_end     = 0.1;
  1097.     context->w3dFog.fog_density = 1.0;
  1098.     context->w3dFog.fog_color.r = 0.0;
  1099.     context->w3dFog.fog_color.g = 0.0;
  1100.     context->w3dFog.fog_color.b = 0.0;
  1101.     context->FogRange           = 1.0;
  1102.  
  1103.     context->CurrentCullFace    = GL_BACK;
  1104.     context->CurrentFrontFace   = GL_CCW;
  1105.  
  1106.     context->ShadeModel         = GL_SMOOTH;
  1107.     context->DepthMask          = GL_TRUE;
  1108.  
  1109.     context->ClearDepth         = 1.0;
  1110.  
  1111. #ifdef AUTOMATIC_LOCKING_ENABLE
  1112.     context->LockMode = MGL_LOCK_MANUAL;
  1113. #endif
  1114.  
  1115.     context->NoMipMapping = newNoMipMapping;
  1116.     context->NoFallbackAlpha = newNoFallbackAlpha;
  1117.  
  1118.     context->Idle = NULL;
  1119.     context->MouseHandler = NULL;
  1120.     context->SpecialHandler = NULL;
  1121.     context->KeyHandler = NULL;
  1122.  
  1123.     context->SrcAlpha = 0;
  1124.     context->DstAlpha = 0;
  1125.     context->AlphaFellBack = GL_FALSE;
  1126.  
  1127.     context->WOne_Hint = GL_FALSE;
  1128.  
  1129.     context->ZOffset = 0.0;
  1130.  
  1131.     context->PaletteData = malloc(4*256);
  1132.     context->PaletteSize = 0;
  1133.     context->PaletteFormat = 0;
  1134.  
  1135.     GLMatrixInit(context);
  1136.     return GL_TRUE;
  1137. }
  1138.  
  1139. void *MGLCreateContext(int offx, int offy, int w, int h)
  1140. {
  1141.     GLcontext context;
  1142.  
  1143.     context = malloc(sizeof(struct GLcontext_t));
  1144.     if (!context)
  1145.     {
  1146.         printf("Error: Can't get %d bytes of memory for context\n", sizeof(struct GLcontext_t));
  1147.         return NULL;
  1148.     }
  1149.  
  1150.     memset(context, 0,  sizeof(struct GLcontext_t));
  1151.  
  1152.     if (newWindowMode == GL_FALSE)
  1153.     {
  1154.         if (GL_FALSE == vid_OpenDisplay(context, w,h, MGL_SM_BESTMODE))
  1155.         {
  1156.             vid_CloseDisplay(context);
  1157.             free(context);
  1158.             printf("Error: opening of display failed\n");
  1159.             return NULL;
  1160.         }
  1161.     }
  1162.     else
  1163.     {
  1164.         if (GL_FALSE == vid_OpenWindow(context, w,h))
  1165.         {
  1166.             vid_CloseWindow(context);
  1167.             free(context);
  1168.             printf("Error: opening of display failed\n");
  1169.             return NULL;
  1170.         }
  1171.     }
  1172.  
  1173.     if (GL_FALSE == MGLInitContext(context))
  1174.     {
  1175.         printf("Error: initalisation of context failed\n");
  1176.         MGLDeleteContext(context);
  1177.         return NULL;
  1178.     }
  1179.  
  1180.     GLDepthRange(context, 0.0, 1.0);
  1181.     GLViewport(context, offy, offy, w, h);
  1182.     GLClearColor(context, 1.0, 1.0, 1.0, 1.0);
  1183.  
  1184.     // Hey, folks, I can do that because I know what I am doing.
  1185.     // You should never read fields from the W3D context that are not
  1186.     // marked as readable...
  1187.     context->w3dChipID = context->w3dContext->CurrentChip;
  1188.  
  1189.     return context;
  1190. }
  1191.  
  1192. void MGLDeleteContext(GLcontext context)
  1193. {
  1194.     GLint current,peak;
  1195.  
  1196.     if (context->w3dBitMap) vid_CloseWindow(context);
  1197.     else                    vid_CloseDisplay(context);
  1198.  
  1199.     if (context->VertexBuffer) free(context->VertexBuffer);
  1200.     if (context->w3dTexBuffer) free(context->w3dTexBuffer);
  1201.  
  1202.     MGLTexMemStat(context, ¤t, &peak);
  1203.     //kprintf("Texture allocation: %ld unfreed, peaked at %ld\n", current, peak);
  1204.  
  1205.     if (CyberGfxBase) CloseLibrary(CyberGfxBase);
  1206.     CyberGfxBase = NULL;
  1207.  
  1208.     free(context);
  1209. }
  1210.  
  1211. #define ED (flag == GL_TRUE?W3D_ENABLE:W3D_DISABLE)
  1212.  
  1213. void MGLSetState(GLcontext context, GLenum cap, GLboolean flag)
  1214. {
  1215.     //LOG(2, mglSetState, "(Enable/Disable) %d -> %d\n", cap, flag);
  1216.     switch(cap)
  1217.     {
  1218.         case GL_ALPHA_TEST:
  1219.             context->AlphaTest_State = flag;
  1220.             W3D_SetState(context->w3dContext, W3D_ALPHATEST, ED);
  1221.             break;
  1222.         case GL_BLEND:
  1223.             context->Blend_State = flag;
  1224.             W3D_SetState(context->w3dContext, W3D_BLENDING, ED);
  1225.             break;
  1226.         case GL_TEXTURE_2D:
  1227.             context->Texture2D_State = flag;
  1228.             W3D_SetState(context->w3dContext, W3D_TEXMAPPING, ED);
  1229.             break;
  1230.         case GL_TEXTURE_GEN_S:
  1231.             context->TextureGenS_State = flag;
  1232.             break;
  1233.         case GL_TEXTURE_GEN_T:
  1234.             context->TextureGenT_State = flag;
  1235.             break;
  1236.         case GL_FOG:
  1237.             context->FogDirty = GL_TRUE;
  1238.             context->Fog_State = flag;
  1239.             W3D_SetState(context->w3dContext, W3D_FOGGING, ED);
  1240.             break;
  1241.         case GL_SCISSOR_TEST:
  1242.             context->Scissor_State = flag;
  1243.             W3D_SetState(context->w3dContext, W3D_SCISSOR, ED);
  1244.             break;
  1245.         case GL_CULL_FACE:
  1246.             context->CullFace_State = flag;
  1247.             break;
  1248.         case GL_DEPTH_TEST:
  1249.             context->DepthTest_State = flag;
  1250.             W3D_SetState(context->w3dContext, W3D_ZBUFFER, ED);
  1251.             if (flag == GL_TRUE)
  1252.             {
  1253.                 if (context->DepthMask)
  1254.                     W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_ENABLE);
  1255.             }
  1256.             else
  1257.             {
  1258.                 W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, W3D_DISABLE);
  1259.             }
  1260.             break;
  1261.         case GL_DITHER:
  1262.             context->Dither_State = flag;
  1263.             W3D_SetState(context->w3dContext, W3D_DITHERING, ED);
  1264.             break;
  1265.         case GL_POINT_SMOOTH:
  1266.             context->PointSmooth_State = flag;
  1267.             W3D_SetState(context->w3dContext, W3D_ANTI_POINT, ED);
  1268.             break;
  1269.         case MGL_PERSPECTIVE_MAPPING:
  1270.             W3D_SetState(context->w3dContext, W3D_PERSPECTIVE, ED);
  1271.             break;
  1272.         case MGL_Z_OFFSET:
  1273.             context->ZOffset_State = flag;
  1274.             break;
  1275.         default:
  1276.             break;
  1277.     }
  1278. }
  1279. #undef ED
  1280.  
  1281. GLint mglGetSupportedScreenModes(MGLScreenModeCallback CallbackFn)
  1282. {
  1283.     W3D_ScreenMode *Modes = W3D_GetScreenmodeList();
  1284.     W3D_ScreenMode *Cursor;
  1285.     MGLScreenMode   sMode;
  1286.     GLboolean       retval;
  1287.  
  1288.     if (Modes == NULL)
  1289.     {
  1290.         return MGL_SM_BESTMODE;
  1291.     }
  1292.  
  1293.     Cursor = Modes;
  1294.     while (Cursor)
  1295.     {
  1296.         sMode.id        = (GLint)Cursor->ModeID;
  1297.         sMode.width     = (GLint)Cursor->Width;
  1298.         sMode.height    = (GLint)Cursor->Height;
  1299.         sMode.bit_depth = (GLint)Cursor->Depth;
  1300.         strncpy(sMode.mode_name, Cursor->DisplayName, MGL_MAX_MODE);
  1301.         retval = CallbackFn(&sMode);
  1302.         if (retval == GL_TRUE)
  1303.         {
  1304.             W3D_FreeScreenmodeList(Modes);
  1305.             return sMode.id;
  1306.         }
  1307.         Cursor = Cursor->Next;
  1308.     }
  1309.     W3D_FreeScreenmodeList(Modes);
  1310.     return MGL_SM_BESTMODE;
  1311. }
  1312.  
  1313. void *MGLCreateContextFromID(GLint id, GLint *width, GLint *height)
  1314. {
  1315.     GLint w,h;
  1316.     GLcontext context;
  1317.  
  1318.     context = malloc(sizeof(struct GLcontext_t));
  1319.     if (!context)
  1320.     {
  1321.         printf("Error: Can't get %d bytes of memory for context\n", sizeof(struct GLcontext_t));
  1322.         return NULL;
  1323.     }
  1324.  
  1325.     memset(context, 0, sizeof(struct GLcontext_t));
  1326.  
  1327.     if (id == MGL_SM_WINDOWMODE) newWindowMode = GL_TRUE;
  1328.  
  1329.     if (newWindowMode == GL_FALSE)
  1330.     {
  1331.         if (GL_FALSE == vid_OpenDisplay(context, -1,-1, (ULONG)id))
  1332.         {
  1333.             vid_CloseDisplay(context);
  1334.             free(context);
  1335.             printf("Error: opening of display failed\n");
  1336.             return NULL;
  1337.         }
  1338.     }
  1339.     else
  1340.     {
  1341.         // Use the other context creation function for Windowed mode.
  1342.         return NULL;
  1343.     }
  1344.  
  1345.     if (GL_FALSE == MGLInitContext(context))
  1346.     {
  1347.         printf("Error: initalisation of context failed\n");
  1348.         MGLDeleteContext(context);
  1349.         return NULL;
  1350.     }
  1351.  
  1352.     w = context->w3dScreen->Width;
  1353.     h = context->w3dScreen->Height;
  1354.     *width = w;
  1355.     *height = h;
  1356.  
  1357.     GLDepthRange(context, 0.0, 1.0);
  1358.     GLViewport(context, 0, 0, w, h);
  1359.     GLClearColor(context, 1.0, 1.0, 1.0, 1.0);
  1360.  
  1361.     // Hey, folks, I can do that because I know what I am doing.
  1362.     // You should never read fields from the W3D context that are not
  1363.     // marked as readable...
  1364.     context->w3dChipID = context->w3dContext->CurrentChip;
  1365.  
  1366.     return context;
  1367. }
  1368.  
  1369.